#include "nn.h"
#define printf(...) 

#define SET_C0_STATUS(val)      asm volatile("mtc0 %0, $12"::"r"(val))           
#define SET_C0_COUNT(val)      asm volatile("mtc0 %0, $9"::"r"(val))             
#define GET_C0_COUNT(val)	asm volatile("mfc0 %0, $9":"=r"(val):)           
#define GET_C0_CAUSE(val)	asm volatile("mfc0 %0, $13":"=r"(val):)          
#define GET_C0_STATUS(val)	asm volatile("mfc0 %0, $12":"=r"(val):)          
#define SET_C0_COMPARE(val)      asm volatile("mtc0 %0, $11"::"r"(val))          
#define TEN_MS (153000000/2)                                                     
#define WRITE_WORD(address,value)  (*(volatile unsigned long *)(address)=value)
#define READ_HALF(address)  (*(volatile unsigned short *)(address))
#define WRITE_HALF(address,value)  (*(volatile unsigned short *)(address)=value)
#define READ_WORD(address)  (*(volatile unsigned long *)(address))
#define WRITE_BYTE(address,value)  (*(volatile unsigned char *)(address)=value)
#define READ_BYTE(address)  (*(volatile unsigned char *)(address))
#define SET_BIT(address,value) (*(volatile unsigned long *)(address)|=value)

#define OTP_CONTROL 0xb8000104
#define OTP_READ_DATA 0xb8000108
#define OTP_SEC_CTRL 0xb800010c
#define OTP_READ_BUSY (1<<27)
#define OTP_READ_TRIG (1<<26)


#define OTP_PUB_BITS	(0x10)
#define OTP_PUB_MOD	(0x14)
#define OTP_PUB_EXP	(0x114) 

#define CPU_MASK_PK  2
#define SEE_MASK_PK  4

#define SYS_SEC_CTRL 0xb8000114
#define EJTAG_LOCK 2
#define EJTAG_DIS  1

//#define addr_outputlen  (unsigned int *)(0x9fc00e10)      //0x80000400
//#define addr_output     (unsigned char *)(0x9fc00e20)   //0x80000500 
   


#define GET_STB_ID(x)  *(unsigned long *)((x) + 0)
#define GET_EJTAG_KEY(x)  *(unsigned long *)((x) + 4)   

unsigned long ali_otp_read(unsigned short addr);
int fetch_pub_key(unsigned long *addr);
   
void Test_RSA()
{
	unsigned long i;
	R_RSA_PUBLIC_KEY Public_Key;
	unsigned int addr_outputlen;
	unsigned char addr_output[256];
	fetch_pub_key((unsigned long *)&Public_Key);//RSA-2048
	
	rsapublicfunc(addr_output,&addr_outputlen,0xa0000a00,0x100,&Public_Key);
  
	if(ali_otp_read(0) == GET_STB_ID(addr_output + 0xe0) &&
	   ali_otp_read(0x174) == GET_EJTAG_KEY(addr_output + 0xe0) &&
	   ali_otp_read(0x178) == GET_EJTAG_KEY(addr_output  + 0xe0 + 4))
  {
  		//*(unsigned char*)(0xb80010b0) = 0x2;   //for debug
  		WRITE_WORD(SYS_SEC_CTRL,READ_WORD(SYS_SEC_CTRL)&~EJTAG_DIS);	             
	}else
	{   
		//	*(unsigned char*)(0xb80010b0) = 0x1;   //for debug
		//  WRITE_WORD(SYS_SEC_CTRL,READ_WORD(SYS_SEC_CTRL)&~EJTAG_DIS);		  
	    WRITE_WORD(SYS_SEC_CTRL,READ_WORD(SYS_SEC_CTRL)|EJTAG_DIS);
      WRITE_WORD(SYS_SEC_CTRL,READ_WORD(SYS_SEC_CTRL)|EJTAG_LOCK);
  }
  
  WRITE_WORD(OTP_SEC_CTRL,READ_WORD(OTP_SEC_CTRL)|SEE_MASK_PK);
  
  for( i = 0; i < 0x100; i += 4)
      *(unsigned long *)(0xa0000000 + i) = 0;
  for( i = 0; i < sizeof(R_RSA_PUBLIC_KEY); i++)
      *(unsigned char *)((unsigned long)(&Public_Key) + i) = 0;

   _clear_and_exit();
  
}

unsigned long ali_otp_read(unsigned short addr)
{
    WRITE_HALF(OTP_CONTROL, addr&0xfffc);
    WRITE_WORD(OTP_CONTROL, READ_WORD(OTP_CONTROL)|OTP_READ_TRIG);
    while(READ_WORD(OTP_CONTROL) & OTP_READ_BUSY);
    return READ_WORD(OTP_READ_DATA);
}

int fetch_pub_key(unsigned long *addr)
{
	int i=0;
	*((unsigned long*)0xB8000220)=*((unsigned long*)0xB8000220) | 0x100;
	WRITE_WORD(OTP_CONTROL,(READ_WORD(OTP_CONTROL)&0xffff0000)|OTP_PUB_BITS);
	while(READ_WORD(OTP_CONTROL) & OTP_READ_BUSY);
	WRITE_WORD(OTP_CONTROL,OTP_PUB_BITS|OTP_READ_TRIG);
	while(READ_WORD(OTP_CONTROL) & OTP_READ_BUSY);
	*(addr)=READ_WORD(OTP_READ_DATA);
	for(i=0;i<64;i++)
	{
		WRITE_WORD(OTP_CONTROL,(READ_WORD(OTP_CONTROL)&0xffff0000)|(OTP_PUB_MOD+(i<<2))|OTP_READ_TRIG);
		while(READ_WORD(OTP_CONTROL) & OTP_READ_BUSY);
		*(addr+i+1)=READ_WORD(OTP_READ_DATA);
	}
	for(i=0;i<56;i++)
	{
		*(addr+i+65)=0;
	}
	for(i=0;i<8;i++)
	{
		WRITE_WORD(OTP_CONTROL,(READ_WORD(OTP_CONTROL)&0xffff0000)|(OTP_PUB_EXP+(i<<2))|OTP_READ_TRIG);
		while(READ_WORD(OTP_CONTROL) & OTP_READ_BUSY);
		*(addr+i+121)=READ_WORD(OTP_READ_DATA);
	}
}

